#ifndef CYCARRAY_H
#define CYCARRAY_H
//system files
#include <mutex>
#include <vector>
#include "queue"
using namespace std;
template<class T>
class CycArray {
  public:
    mutable mutex mtx_q;       //多线程互斥锁
    int total_size;       //数组长度(总长度)
    int current_size; //有效数据长度
    queue<T> q;

    CycArray();
    CycArray(const int len);

    // Copy initialization
    CycArray(const CycArray& other);

    // Copy assignment
    CycArray<T> & operator = (const CycArray<T>& other) {
        std::lock(mtx_q, other.mtx_q);
        std::lock_guard<std::mutex> self_lock(mtx_q, std::adopt_lock);
        std::lock_guard<std::mutex> other_lock(other.mtx_q, std::adopt_lock);
        q=other.q;
        total_size=other.total_size;
        current_size=other.current_size;
//        std::printf("done CycArray Copy assignment"
//                    "================================\n");
        return *this;
    }

    void Init(const int len);

    void Update(T t);      //添加一条新数据

    void Clear();     //清空队列

    bool Last(T &result); //返回最后一条数据(the "newest" element in the queue)

    bool GetLatest(int num, vector<T> &result);  //返回最新num条数据

    bool ToArray(vector<T> &result); //所有数据以数组返回, 舊數據在前,新數據在後

    bool ToArrayR(vector<T> &result); //倒序生成数组    //新數據在前 舊數據在後

    //手动加锁解锁
    void ManualLock();
    void ManualUnlock();
    void ManualClear();
    bool ManualToArray(vector<T> &result);
    void ManualUpdate(T t);
};

template<class T>
CycArray<T>::CycArray() {
    total_size=100;
    current_size=0;
}

//构造函数，传入总长度
template<class T>
CycArray<T>::CycArray(const int len) {
    total_size = len;     //总长度赋值
    current_size=0;
}

// Copy initialization
template<class T>
CycArray<T>::CycArray(const CycArray& other) {
    std::lock_guard<std::mutex> lock(other.mtx_q);
    total_size = other.total_size;
    current_size = other.current_size;
    q=other.q;
//    std::printf("done CycArray Copy Initialization"
//                "================================\n");
}

//初始化cyc array
template<class T>
void CycArray<T>::Init(const int len) {
    total_size=len;
    current_size=0;
}

//添加一条新数据
template<class T>
void CycArray<T>::Update(T t) {
    if(total_size<=0) {
        return;
    }
    mtx_q.lock(); //加互斥锁
    q.push(t);  //添加数据到队列
    ++current_size;
    if(current_size>total_size) { //如果超长，弹出一个
        q.pop();//the "oldest" element in the queue
        --current_size;
    }
    mtx_q.unlock();//解互斥锁
}

//清空队列
template<class T>
void CycArray<T>::Clear() {
    mtx_q.lock();//加互斥锁
    while(!q.empty()) {
        //the "oldest" element in the queue
        //the same element that is popped out from the queue when queue::pop is called.
        q.pop();
        --current_size;
    }
    mtx_q.unlock();//解互斥锁
}

//返回最后一条数据(the "newest" element in the queue)
template<class T>
bool CycArray<T>::Last(T &result) {
    {
        //开始锁
        lock_guard<mutex> lg(mtx_q); //锁管理器
        if(current_size>0) {
            result=q.back();//the "newest" element in the queue
            return true;
        } else {
            return false;
        }
    }//结束锁
}

//取队列最新的num条数据
//舊數據在前,新數據在後
//如果num大于现有数据，返回所有数据
template<class T>
bool CycArray<T>::GetLatest(int num, vector<T> &result) {
    {
        int num_using=num;
        lock_guard<mutex> lg(mtx_q); //锁管理器
        if(num<=0) { //越界
            return false;
        }
        if(current_size<num) {
            num_using=current_size;
        }
        for(int i=0; i < current_size; i++) {
            T tmp=q.front(); //暂存并弹出首元素
            q.pop();
            if(i>=current_size-num_using) { //取值
                result.push_back(tmp);
            }
            q.push(tmp);//重新压回原队列
        }
        return true;
    }
}

//所有数据以数组返回
//舊數據在前,新數據在後
template<class T>
bool CycArray<T>::ToArray(vector<T> &result) {
    {
        lock_guard<mutex> lg(mtx_q); //锁管理器
        if(current_size<=0) {
            return false;
        }
        for(int i=0; i<current_size; i++) {
            T tmp=q.front(); //暂存并弹出首元素
            q.pop();
            result.push_back(tmp);
            q.push(tmp);//重新压回原队列
        }
        return true;
    }
}

//倒序生成数组
//新數據在前 舊數據在後
template<class T>
bool CycArray<T>::ToArrayR(vector<T> &resultR) {
    {
        vector<T> result;//顺序元素
        lock_guard<mutex> lg(mtx_q); //锁管理器
        if(current_size<=0) {
            return false;
        }
        for(int i=0; i<current_size; i++) {
            T tmp=q.front(); //暂存并弹出首元素
            q.pop();//the "oldest" element in the queue
            result.push_back(tmp);
            q.push(tmp);//重新压回原队列
        }
        for(int i=0; i<current_size; i++) {
            resultR.push_back(result[current_size-1-i]);
        }
        return true;
    }
}
//Manual lock and un lock==========================
//手动加锁
template<class T>
void CycArray<T>::ManualLock() {
    mtx_q.lock();
}
//手动解锁
template<class T>
void CycArray<T>::ManualUnlock() {
    mtx_q.unlock();
}
//清空队列 手动加解锁模式下
template<class T>
void CycArray<T>::ManualClear() {
    while(!q.empty()) {
        //the "oldest" element in the queue
        //the same element that is popped out from the queue when queue::pop is called.
        q.pop();
        --current_size;
    }
}
//转换到数组 手动加解锁模式下
template<class T>
bool CycArray<T>::ManualToArray(vector<T> &result) {
    if(current_size<=0) {
        return false;
    }
    for(int i=0; i<current_size; i++) {
        T tmp=q.front(); //暂存并弹出首元素
        q.pop();
        result.push_back(tmp);
        q.push(tmp);//重新压回原队列
    }
    return true;
}

//更新一条数据 手动加解锁模式下
template<class T>
void CycArray<T>::ManualUpdate(T t) {
    if(total_size<=0) {
        return;
    }
    q.push(t);  //添加数据到队列
    ++current_size;
    if(current_size>total_size) { //如果超长，弹出一个
        q.pop();//the "oldest" element in the queue
        --current_size;
    }
}

#endif // CYCARRAY_H
